import tkinter as tk
from tkinter import ttk, messagebox
import time
import threading
from pynput import keyboard
import json
import pyautogui

from scrollable_widgets import create_scrollable_canvas, create_scrollable_text
from utils import create_centered_window, bind_mousewheel


class DelaySettingsDialog:
    def __init__(self, parent, delay_settings):
        self.window = create_centered_window(title="默认操作延迟设置", width=350, height=450, window_type='top',
                                             parent=parent)
        # 强制用户必须先处理对话框
        self.window.grab_set()

        # 创建传入字典的副本，避免直接修改原始数据
        # 这样做可以实现"取消"功能，用户点击取消时不会修改原始设置
        # 只有用户点击"确定"时，才会将修改后的值返回并更新原始字典
        self.delay_settings = delay_settings.copy()
        # 存储修改结果，用于传递回主窗口
        self.result = None

        # 存储Entry引用的字典
        self.delay_entries = None

        self.create_ui()

    def create_ui(self):
        # 创建主框架
        main_frame = ttk.Frame(self.window, padding=10)
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 添加说明标签
        info_label = ttk.Label(main_frame,
                               text="延迟时间表示步骤执行完成后等待的时间",
                               font=("微软雅黑", 9),
                               foreground="blue")
        info_label.pack(pady=(0, 10))

        # 创建滚动区域
        canvas = create_scrollable_canvas(main_frame, height=150, highlightthickness=0)
        # 放置滚动区域
        canvas.pack(fill="both", expand=True)

        scrollable_frame = ttk.Frame(canvas)

        canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")

        # 定义延迟设置项：(显示名称, 键名, 默认值)
        delay_settings_items = [
            ("单击延迟 (秒):", "click", 1.0),
            ("双击延迟 (秒):", "double_click", 1.0),
            ("输入延迟 (秒):", "input", 1.0),
            ("回车延迟 (秒):", "enter", 1.0),
            ("默认延迟 (秒):", "default", 1.0)
        ]

        # 动态创建延迟设置项
        self.delay_entries = {}  # 存储Entry引用的字典
        for i, (label, key, default_value) in enumerate(delay_settings_items):
            # 创建标签
            ttk.Label(scrollable_frame, text=label).grid(
                row=i, column=0, sticky=tk.W, padx=5, pady=5
            )

            # 创建输入框
            entry = ttk.Entry(scrollable_frame, width=10)
            entry.grid(row=i, column=1, pady=2, padx=(10, 0))
            entry.insert(0, str(self.delay_settings.get(key, default_value)))

            # 存储Entry引用，便于后续访问,{'click': entry, 'input': entry, ...}
            self.delay_entries[key] = entry

        # 更新滚动区域以包含所有内容
        scrollable_frame.update_idletasks()
        canvas.configure(scrollregion=canvas.bbox("all"))

        # 窗口绑定鼠标滚轮事件
        bind_mousewheel(canvas, self.window)

        # 按钮框架 - 使用pack并确保可见
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(fill=tk.X, pady=(10, 0))

        # 添加确定按钮说明
        confirm_info = ttk.Label(button_frame,
                                 text="点击'取消'放弃更改，点击'确定'保存设置",
                                 font=("微软雅黑", 8),
                                 foreground="gray")
        confirm_info.pack(pady=(0, 5))

        # 按钮容器框架
        buttons_container = ttk.Frame(button_frame)
        buttons_container.pack()

        # 按钮
        cancel_button = ttk.Button(buttons_container, text="取消", command=self.cancel)
        cancel_button.pack(side=tk.LEFT, padx=5)

        ok_button = ttk.Button(buttons_container, text="确定", command=self.ok)
        ok_button.pack(side=tk.LEFT, padx=5)

    def ok(self):
        try:
            self.result = {
                'click': float(self.delay_entries["click"].get()),
                'double_click': float(self.delay_entries["double_click"].get()),
                'input': float(self.delay_entries["input"].get()),
                'enter': float(self.delay_entries["enter"].get()),
                'default': float(self.delay_entries["default"].get())
            }
            self.window.destroy()
        except ValueError:
            messagebox.showerror("错误", "请输入有效的数字")

    def cancel(self):
        self.window.destroy()


class CustomDelaySettingsDialog:
    def __init__(self, parent, steps, custom_delay_settings):
        self.window = create_centered_window(title="自定义步骤延迟设置", width=400, height=500, window_type='top',
                                             parent=parent)
        # 强制用户必须先处理对话框
        self.window.grab_set()

        self.steps = steps
        self.custom_delay_settings = custom_delay_settings.copy()  # 创建副本避免直接修改原始数据
        self.result = None  # 存储修改结果

        # 存储所有步骤延迟输入框的引用，用于后续获取输入值
        # 格式: [Entry组件, ...]
        self.entries = []

        self.create_ui()

    def create_ui(self):
        # 创建主框架
        main_frame = ttk.Frame(self.window, padding=10)
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 创建滚动区域,去除Canvas的焦点高亮边框
        canvas = create_scrollable_canvas(main_frame, height=150, highlightthickness=0)
        canvas.pack(fill="both", expand=True)

        scrollable_frame = ttk.Frame(canvas)
        canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")

        # 为窗口绑定鼠标滚轮事件
        bind_mousewheel(canvas, self.window)

        # 存储所有步骤延迟输入框的引用，用于后续获取输入值
        # 格式: [Entry组件, ...]
        self.entries = []
        for i, step_data in enumerate(self.steps):
            step_name = step_data.get('name', f'步骤 {i + 1}')

            frame = ttk.Frame(scrollable_frame)
            frame.pack(pady=5)

            ttk.Label(frame, text=f"{step_name}:").pack(side=tk.LEFT, padx=10)

            # 创建Entry组件
            entry = ttk.Entry(frame, width=10)
            step_delay = self.custom_delay_settings.get(str(i), "")
            if step_delay != "": entry.insert(0, str(step_delay))
            entry.pack(side=tk.LEFT)
            self.entries.append(entry)

        # 更新滚动区域以包含所有内容
        canvas.update_idletasks()
        canvas.configure(scrollregion=canvas.bbox("all"))

        # 按钮框架 - 放在滚动区域外面
        button_frame = ttk.Frame(self.window, padding="10")
        button_frame.pack(fill=tk.X)

        # 重置所有延迟按钮
        reset_button = ttk.Button(button_frame, text="重置所有延迟", command=self.reset_all_delays)
        reset_button.pack(side=tk.LEFT, padx=(0, 5))

        # 保存按钮
        save_button = ttk.Button(button_frame, text="保存", command=self.ok)
        save_button.pack(side=tk.RIGHT, padx=(5, 0))

        # 取消按钮
        cancel_button = ttk.Button(button_frame, text="取消", command=self.cancel)
        cancel_button.pack(side=tk.RIGHT)

    def reset_all_delays(self):
        """重置所有延迟设置"""
        for entry in self.entries:
            entry.delete(0, tk.END)

    def ok(self):
        """保存设置"""
        try:
            self.result = {}
            for index, entry in enumerate(self.entries):
                value = entry.get().strip()
                if value:
                    delay = float(value)
                    self.result[str(index)] = delay
            self.window.destroy()
        except ValueError:
            tk.messagebox.showerror("错误", "请输入有效的数字")

    def cancel(self):
        """取消操作"""
        self.window.destroy()


class AutoExecutor:
    def __init__(self, workflow_data, workflow_file, main_window):
        self.workflow_data = workflow_data
        self.workflow_file = workflow_file
        self.main_window = main_window

        # 原始步骤配置
        self.steps = workflow_data.get("steps", [])
        # 默认延迟设置
        self.delay_settings = workflow_data.get("delay_settings", {
            "click": 1.0,
            "double_click": 1.0,
            "input": 1.0,
            "enter": 1.0,
            "default": 1.0
        })
        # 步骤延迟设置
        self.custom_delay_settings = workflow_data.get("custom_delay_settings", {})

        # 步骤函数列表
        self.step_functions = []
        self.create_step_functions()

        # 执行状态
        self.current_step = 0
        self.is_running = False
        self.is_paused = False

        # UI组件
        self.progress_bar = None
        self.log_area = None
        self.start_button = None
        self.step_label = None

        # 键盘监听器
        self.stop_key_listener = None

        self.root = create_centered_window(title="自动执行器", width=900, height=700, window_type='top',
                                           parent=main_window)

        # 添加窗口关闭协议处理
        self.root.protocol("WM_DELETE_WINDOW", self.back_to_main)

        # 创建UI
        self.create_ui()

    def create_step_functions(self):
        """根据步骤数据创建可执行的函数列表"""
        for step_data in self.steps:
            # 每次循环都创建新的函数
            def step_func(data=step_data):  # 使用默认参数避免闭包问题
                # 根据步骤类型执行不同的操作
                step_type = data.get('type')
                if step_type == "click":
                    pyautogui.click(data['x'], data['y'])
                elif step_type == "double_click":
                    pyautogui.doubleClick(data['x'], data['y'])
                elif step_type == "input":
                    pyautogui.write(data['value'])
                elif step_type == "enter":
                    pyautogui.press('enter')
                else:
                    print(f"未知的步骤类型: {step_type}")

            # 为每个函数设置属性
            step_func.step_data = step_data
            self.step_functions.append(step_func)

    def create_ui(self):
        """设置用户界面"""
        # 主框架
        main_frame = ttk.Frame(self.root, padding=20)
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 步骤显示框架
        step_frame = ttk.LabelFrame(main_frame, text="执行进度", padding="10")
        step_frame.pack(fill=tk.X, pady=(0, 10))

        self.step_label = ttk.Label(step_frame, text="步骤: 0/0")
        # 在可用空间内左对齐
        self.step_label.pack(anchor=tk.W)

        self.progress_bar = ttk.Progressbar(step_frame, mode='determinate')
        self.progress_bar.pack(fill=tk.X, pady=(5, 0))
        self.progress_bar['maximum'] = len(self.steps)

        # 控制按钮框架
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(fill=tk.X, pady=(0, 10))

        # 按钮容器框架
        buttons_container = ttk.Frame(button_frame)
        buttons_container.pack()

        # 自动模式下添加开始和返回按钮
        self.start_button = ttk.Button(buttons_container, text="开始执行", command=self.start_execution)
        self.start_button.pack(side=tk.LEFT, padx=(0, 10))

        # 添加重置按钮
        reset_button = ttk.Button(buttons_container, text="重置到第一步",
                                  command=self.reset_to_first_step)
        reset_button.pack(side=tk.LEFT, padx=(0, 10))

        # 添加延迟设置按钮
        delay_button = ttk.Button(buttons_container, text="默认操作延迟设置", command=self.set_delay_settings)
        delay_button.pack(side=tk.LEFT, padx=(0, 10))

        # 添加步骤延迟设置按钮
        step_delay_button = ttk.Button(buttons_container, text="自定义步骤延迟设置",
                                       command=self.set_custom_delay_setting)
        step_delay_button.pack(side=tk.LEFT, padx=(0, 10))

        back_button = ttk.Button(buttons_container, text="返回主窗口", command=self.back_to_main)
        back_button.pack(side=tk.LEFT, padx=(0, 10))

        # 添加提示信息
        hotkey_hint = ttk.Label(button_frame, text="热键提示: 按 Ctrl 键停止执行", foreground="red",
                                font=("微软雅黑", 10, "bold"))
        hotkey_hint.pack(pady=(10, 0))

        # 日志区域
        log_frame = ttk.LabelFrame(main_frame, text="执行日志", padding="10")
        log_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 10))

        # 创建日志区域
        self.log_area = create_scrollable_text(log_frame, state=tk.DISABLED)
        self.log_area.pack(fill=tk.BOTH, expand=True)

        # 给Text组件绑定滚动，并且覆盖掉默认行为
        bind_mousewheel(self.log_area)
        # 给根窗口绑定滚动
        bind_mousewheel(self.log_area, self.root)

        # 初始化进度条UI状态
        self.update_progress()

    def set_delay_settings(self):
        """设置默认延迟时间"""
        dialog = DelaySettingsDialog(self.root, self.delay_settings)
        # 等待默认延迟框关闭
        self.root.wait_window(dialog.window)

        if dialog.result:
            self.delay_settings = dialog.result
            self.save_delay_settings()
            self.log_message("默认操作延迟设置已更新")

    def set_custom_delay_setting(self):
        """设置自定义步骤延迟时间"""
        dialog = CustomDelaySettingsDialog(self.root, self.steps, self.custom_delay_settings)
        # 等待自定义步骤延迟框关闭
        self.root.wait_window(dialog.window)

        if dialog.result is not None:
            self.custom_delay_settings = dialog.result
            self.save_delay_settings()
            self.log_message("自定义步骤延迟设置已更新")

    def register_stop_hotkey(self):
        """注册停止热键"""

        def on_press(key):
            # 检查是否在自动执行状态下按下Ctrl键
            if key in [keyboard.Key.ctrl_l, keyboard.Key.ctrl_r] and self.is_running:
                self.stop_execution()
                return False  # 停止监听

        # 创建并启动监听器
        self.stop_key_listener = keyboard.Listener(on_press=on_press)
        self.stop_key_listener.start()
        self.log_message("已注册停止热键: 按 Ctrl 键停止执行")

    def update_progress(self):
        """更新步骤标签"""
        self.step_label.config(
            text=f"步骤: {self.current_step}/{len(self.steps)}")
        self.progress_bar['value'] = self.current_step
        # 强制进度条更新
        self.progress_bar.update_idletasks()

    def log_message(self, message: str):
        """记录日志信息"""
        if self.log_area:  # 只有当log_area存在时才记录日志
            self.log_area.config(state=tk.NORMAL)
            timestamp = time.strftime("%H:%M:%S", time.localtime())
            self.log_area.insert(tk.END, f"[{timestamp}] {message}\n")
            self.log_area.see(tk.END)
            self.log_area.config(state=tk.DISABLED)

    def get_step_delay(self, step_index):
        """获取指定步骤的延迟时间"""
        # 优先使用步骤特定延迟，否则使用类型延迟，最后使用默认延迟
        step_delay = self.custom_delay_settings.get(str(step_index))
        if step_delay is not None:
            return step_delay

        # 获取步骤类型
        if step_index < len(self.steps):
            step_type = self.steps[step_index].get('type', 'default')
            return self.delay_settings.get(step_type, self.delay_settings['default'])

        return self.delay_settings['default']

    def reset_to_first_step(self):
        # 如果正在运行，则先停止执行
        if self.is_running:
            self.stop_execution()
        # 重置到第一步
        self.current_step = 0
        self.update_progress()
        self.log_message("已重置到第一步")

    def reset_execution_state(self):
        """重置执行状态"""
        self.current_step = 0
        self.is_running = False
        self.is_paused = False

    def save_delay_settings(self):
        """保存延迟设置到工作流文件"""
        try:
            # 构建完整的工作流数据，包含所有数据
            workflow_data = {
                'steps': self.steps,
                'delay_settings': self.delay_settings,
                'custom_delay_settings': self.custom_delay_settings
            }

            # 保存到文件
            with open(self.workflow_file, 'w', encoding='utf-8') as f:
                json.dump(workflow_data, f, ensure_ascii=False, indent=2)
        except Exception as e:
            self.log_message(f"保存延迟设置失败: {e}")

    def start_execution(self):
        """开始执行"""
        # 最小化窗口
        self.root.iconify()

        self.is_running = True
        self.is_paused = False

        # 更新按钮状态
        if self.start_button:
            self.start_button.config(state=tk.DISABLED)

        # 注册停止热键
        self.register_stop_hotkey()

        # 启动执行线程
        execution_thread = threading.Thread(target=self._execute_steps)
        execution_thread.daemon = True
        execution_thread.start()

        self.log_message("开始执行自动化步骤...")
        self.log_message("提示: 按 Ctrl 键可随时停止执行")

    def stop_execution(self):
        """停止执行"""
        self.is_running = False
        self.is_paused = False
        self.log_message("执行已停止")
        # 清理执行状态
        if self.start_button:
            self.start_button.config(state=tk.NORMAL)
        # 注销停止热键
        if self.stop_key_listener:
            self.stop_key_listener.stop()
            self.stop_key_listener = None

    def back_to_main(self):
        """返回主窗口"""
        # 如果正在运行，则先停止执行
        if self.is_running:
            self.stop_execution()
        # 销毁执行器窗口
        self.root.destroy()
        # 显示主窗口
        self.main_window.deiconify()

    def _execute_steps(self):
        """执行步骤（在单独线程中运行）"""
        while self.is_running and self.current_step < len(self.steps):
            # 执行当前步骤
            try:
                step_func = self.step_functions[self.current_step]
                # 获取步骤名称
                step_name = step_func.step_data.get('name', '未知步骤')
                self.log_message(f"执行步骤 {self.current_step + 1}: {step_name}")
                step_func()

                # 更新UI
                self.current_step += 1
                self.update_progress()

                # 添加延迟
                delay = self.get_step_delay(self.current_step - 1)
                self.log_message(f"步骤 {self.current_step} 使用延迟: {delay}秒")
                time.sleep(delay)

                # 检查是否完成一轮执行
                if self.current_step >= len(self.steps):
                    self.log_message("一轮执行完成，重新开始")
                    self.current_step = 0
                    self.update_progress()

            except Exception as e:
                self.log_message(f"执行步骤 {self.current_step + 1} 时出错: {str(e)}")
                if self.is_running:  # 只有在非手动停止的情况下才结束
                    self.stop_execution()
